<?php
require_once 'ILog.class.php';
/**
 * Classe abstrata para o componente Log da aplicação.
 *
 * @author tiago
 */
class AbstractLog {
    
    /**
     * Caminho atual do sistema de arquivos.
     * 
     * @var type string
     */
    private $caminhoAtual;
    
    /**
     * Nome que será usado para identificar log, quando for diferenciar por
     * usuário ou etc.
     * 
     * @var type string
     */
    private $nomeArquivo;
    
    /**
     * Construtor.
     */
    public function __construct($nomeArquivo = '') {
        $this->setNomeArquivo($nomeArquivo);
    }
    
    /**
     * Verifica qual o nivel de log habilitado.
     */
    public function getLogLevel() {
    	return IApplicationConfig::LOG_LEVEL;
    }
    
    /**
     * Verifica se o nível de log Trace está habilitado.
     * */
    public function isTraceEnabled() {
        return $this->getLogLevel() == ILog::TRACE;
    }
    
    /**
     * Verifica se o nível de log Debug está habilitado.
     * */
    public function isDebugEnabled() {
        return ($this->getLogLevel() >= ILog::DEBUG);
    }
    
    /**
     * Verifica se o nível de log Info está habilitado.
     * */
    public function isInfoEnabled() {
        return ($this->getLogLevel() >= ILog::INFO);
    }
    
    /**
     * Log para trace.
     * */
    public function logTrace($msg) {
        if(IApplicationConfig::LOG_LEVEL == ILog::TRACE) {
            $dbgTrc = debug_backtrace();
            $caller = $dbgTrc[0];//pegando a primeira posição
            //$caller = reset(debug_backtrace());/* Primeira posicao do array */
            $this->logar($msg, 'trace', $caller);
        }
    }
    
    /**
     * Log para debug.
     * */
    public function logDebug($msg) {
        if(IApplicationConfig::LOG_LEVEL >= ILog::DEBUG) {
            $dbgTrc = debug_backtrace();
            $caller = $dbgTrc[0];//pegando a primeira posição
            //$caller = reset(debug_backtrace());/* Primeira posicao do array */
            $this->logar($msg, 'debug', $caller);
        }
    }
    
    /**
     * Log para info.
     * */
    public function logInfo($msg) {
        if(IApplicationConfig::LOG_LEVEL >= ILog::INFO) {
            $dbgTrc = debug_backtrace();
            $caller = $dbgTrc[0];//pegando a primeira posição
            //$caller = reset(debug_backtrace());/* Primeira posicao do array */
            $this->logar($msg, 'info', $caller);
        }
    }
    
    /**
     * Log para error.
     * */
    public function logError($msg) {
        $dbgTrc = debug_backtrace();
        $caller = $dbgTrc[0];//pegando a primeira posição
        //$caller = reset(debug_backtrace());/* Primeira posicao do array */
        $this->logar($msg, 'ERROR', $caller);
    }
    
    /**
     * Metodo para recuperar a data e hora do log.
     */
    private function getDtLog() {
        return date('d/m/Y H:i:s:') . $this->getMilisecond();
    }
    
    /**
     * Metodo para recuperar o milisegundo da hora atual.
     */
    private function getMilisecond() {
        $t = explode('.', microtime(true));
        return substr($t[count($t) - 1] . '000', 0, 3);
    }
    
    /**
     * Método muda o contexto para a pasta de log.
     * Abre e retorna o arquivo de log.
     * 
     * @return file Arquivo de log.
     */
    private function abrirArquivo() {
        /* Preservando o caminho atual */
        $this->caminhoAtual = getcwd();
        
        /* Muda o contexto de execução para a pasta logs */
        switch (IApplicationConfig::ENVIRONMENT) {
            case IApplicationConfig::PRODUCTION:
                chdir(IApplicationConfig::LOG_PROD_FOLDER);
                break;
            case IApplicationConfig::UAT:
                chdir(IApplicationConfig::LOG_UAT_FOLDER);
                break;
            default :
                chdir(IApplicationConfig::LOG_DEV_FOLDER);
                break;
        }

        $filename = 'Log.' . date('Y-m-d-H');
        if(IApplicationConfig::ENABLED_NAME_DIF && $this->nomeArquivo != '') {
            $filename .= '[' . $this->nomeArquivo . ']';
        }
        $filename .= '.log';
        return fopen($filename, 'a');
    }
    
    /**
     * Fecha o arquivo de log e muda o contexto para a pasta atual.
     */
    private function fecharArquivo($arq) {
        /* Fechando o arquivo de log */
        fclose($arq);
        
        /* Voltando o contexto para o caminho atual */
        chdir($this->caminhoAtual);
    }

    /**
     * Método setter para $nomeArquivo.
     * 
     * @param type string $nomeArquivo
     */
    private function setNomeArquivo($nomeArquivo) {
        $this->nomeArquivo = $nomeArquivo;
    }
    
    /**
     * Metodo usado para escrever no arquivo.
     */
    private function escrever($arq, $msg, $level, $caller) {
        fwrite($arq, '[' . $this->getDtLog() . '][' . $level . '][' . $caller['file'] . ',' . $caller['line'] . '] '. $msg . "\n");
    }
    
    /**
     * Executa a ação de logar a mensagem em um arqivo de texto.
     */
    private function logar($msg, $level, $caller) {
        $arq = $this->abrirArquivo();
        $this->escrever($arq, $msg, $level, $caller);
	$this->fecharArquivo($arq);
    }
}
